﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Globalization;
using System.Text.RegularExpressions;

namespace SocialWebpart
{
    public partial class SocialWebpart
    {
        /// <summary>
        /// To get twitter feeds
        /// </summary>
        public class TwitterFeeds
        {
            //Mapped to Access Token
            private string APIOauthToken = string.Empty;
            //Mapped to Access token secret
            private string APIOauthTokenSecret = string.Empty;
            //Map it to Consumer Key
            private string APIOauthAccessKey = string.Empty;
            //Mapped to Consumer Secret
            private string APIOauthAccessToken = string.Empty;
            //Actuall user twitter id
            private string UserID = string.Empty;

            private string OauthVersion = "1.0";
            private string OauthSignatureMethod = "HMAC-SHA1";
            
            /// <summary>
            /// Setting Webpart properties like Oauth Token, Secret code, access key, access key secret
            /// </summary>
            /// <param name="facebookUserId">User ID</param>
            /// <param name="facebookTokenCode">Token Code</param>
            /// <param name="facebookPostsCount">Facebook post count</param>
            public TwitterFeeds(string apiOauthToken, string apiOauthTokenSecret, string apiOauthAccessKey, string apiOauthAccessToken, string strUserID)
            {
                this.APIOauthToken = apiOauthToken;
                this.APIOauthTokenSecret = apiOauthTokenSecret;
                this.APIOauthAccessKey = apiOauthAccessKey;
                this.APIOauthAccessToken = apiOauthAccessToken;
                this.UserID = strUserID;
            }

            /// <summary>
            /// This method returns Twitter feed control
            /// </summary>
            /// <returns></returns>
            public WebControl GetTwitterFeeds()
            {
                //Control for Twitter 
                WebControl divTwitterParent = new WebControl(HtmlTextWriterTag.Div);
                divTwitterParent.Controls.Add(new Literal()
                {
                    Text = "<div class='tab-content' id='Twitter-tab'>"
                });

                try
                {
                    if (CheckTwitterControlProperties())
                    {
                        List<RootObject> jsonObj = GetTweets();
                        Table mainTable = new Table();
                        TableRow tr;
                        TableCell tc;

                        mainTable.Width = Unit.Percentage(100);
                        mainTable.CssClass = "webpart-twitter-table-content";

                        if (null != jsonObj && jsonObj.Count > 0)
                        {
                            int jsonCount = jsonObj.Count;
                            for (int i = 0; i < jsonCount; i++)
                            {
                                tr = new TableRow();
                                tc = new TableCell();
                                tc.Width = Unit.Percentage(25);
                                tc.Controls.Add(BuildTwitterProfileImage(jsonObj[i]));
                                tr.Controls.Add(tc);
                                tc = new TableCell();
                                tc.Controls.Add(BuildTwitterFeed(jsonObj[i]));
                                tr.Controls.Add(tc);
                                mainTable.Controls.Add(tr);
                                divTwitterParent.Controls.Add(mainTable);
                            }
                        }
                        else
                        {
                            //Json is null
                        }
                    }
                    else
                    {
                        //Properties are not set
                    }
                }
                catch (Exception Ex)
                {
                    //Handle exception
                }
                return divTwitterParent;
            }

            /// <summary>
            /// This method build twitter profile image
            /// </summary>
            /// <param name="feed"></param>
            /// <returns></returns>
            private WebControl BuildTwitterProfileImage(RootObject feed)
            {
                WebControl control = new WebControl(HtmlTextWriterTag.Div);
                if (feed != null && !string.IsNullOrEmpty(feed.user.profile_image_url))
                {
                    string imgUrl = feed.user.profile_image_url;
                    control.Controls.Add(new LiteralControl("<img src=" + imgUrl + "></img>"));
                }
                return control;
            }

            /// <summary>
            /// This method build twitter feeds
            /// </summary>
            /// <param name="feed"></param>
            /// <returns></returns>
            private WebControl BuildTwitterFeed(RootObject feed)
            {
                Table tweetDetails = new Table();
                TableRow tweetRow = new TableRow();
                TableCell tweetCell = new TableCell();
                if (feed.user != null && !string.IsNullOrEmpty(feed.user.screen_name))
                {
                    string displayName = feed.user.screen_name;
                    string ctr = "<a href=" + "http://twitter.com/" +"><span>" + displayName + "</span></a>";
                    tweetCell.Controls.Add(new LiteralControl(ctr));
                    tweetRow.Controls.Add(tweetCell);
                    tweetDetails.Controls.Add(tweetRow);
                }
                else
                {
                    //Set it for default twitter
                }

                if (feed.text != null)
                {
                    tweetRow = new TableRow();
                    tweetCell = new TableCell();
                    string tweetText = feed.text;
                    if (feed.retweeted)
                    {
                        try
                        {
                            string[] str = tweetText.Split(':');
                            string strRtMessage = feed.retweeted_status.text;
                            if (str.Count() > 0)
                            {
                                tweetText = str[0] + ": " + strRtMessage;
                            }
                        }
                        catch (Exception e)
                        {
                        }
                    }
                    
                    tweetCell.Text = ConvertUrlsToLinks(tweetText);
                    tweetRow.Controls.Add(tweetCell);
                    tweetDetails.Controls.Add(tweetRow);
                }

                if (feed.created_at != null)
                {
                    tweetCell = new TableCell();
                    tweetRow = new TableRow();
                    tweetCell.Text = RelativeTime(feed.created_at);
                    tweetRow.Controls.Add(tweetCell);
                    tweetDetails.Controls.Add(tweetRow);
                }
                return tweetDetails;
            }

            /// <summary>
            /// Facebook message/post return from api are plain text, we need to convert that to html
            /// </summary>
            /// <param name="message"></param>
            /// <returns></returns>
            private string ConvertUrlsToLinks(string message)
            {
                string strMessage = message;
                try
                {
                    strMessage = Regex.Replace(strMessage, @"(http?://([-\w\.]+)+(/([\w/_\.]*(\?\S+)?(#\S+)?)?)?)", "<a href='$1' target='_blank'>$1</a>");
                    strMessage = Regex.Replace(strMessage, @"(htts?://([-\w\.]+)+(/([\w/_\.]*(\?\S+)?(#\S+)?)?)?)", "<a href='$1' target='_blank'>$1</a>");
                    strMessage = Regex.Replace(strMessage, @"\s+#(\w+)", " <a href='http://twitter.com/search?q=%23$1' target='_blank'>#$1</a>");
                    strMessage = Regex.Replace(strMessage, @"@(\w+)", "@<a href='http://twitter.com/$1' target='_blank'>$1</a>");
                }
                catch (Exception ex)
                {
                //Handle exception
                }
                return strMessage;
            }

            /// <summary>
            /// This method returns the relative time of facebook post
            /// </summary>
            /// <param name="postTime">Returns date time in string format</param>
            /// <returns>Returns text to display in the webpart</returns>
            private string RelativeTime(string postTime)
            {
                DateTime objOriginalTimeStamp = DateTime.ParseExact(postTime,
                                  "ddd MMM dd HH:mm:ss zzz yyyy",
                                  CultureInfo.InvariantCulture);
                DateTime objpostTime = objOriginalTimeStamp;
                //DateTime objOriginalTimeStamp = DateTime.Parse(postTime);
                DateTime objCurrentDate = DateTime.Now;

                TimeSpan objTimespan = objCurrentDate.Subtract(objOriginalTimeStamp);
                string strReturn = string.Empty;

                if (objTimespan.Days >= 1)
                {
                    strReturn = String.Format("{0:hh:mm tt MMM dd}" + "th", Convert.ToDateTime(objpostTime).ToUniversalTime());
                }
                else
                {
                    if (objTimespan.Hours >= 1)
                        strReturn = "about " + objTimespan.Hours + " hours ago";
                    else
                    {
                        if (objTimespan.Minutes >= 1)
                        {
                            strReturn = "about " + objTimespan.Minutes + " minutes ago";
                        }
                        else
                            strReturn = "about " + objTimespan.Seconds + " seconds ago";
                    }
                }
                return strReturn;
            }

            /// <summary>
            /// This method check if all the twitter properties are set or not
            /// </summary>
            /// <returns></returns>
            private bool CheckTwitterControlProperties()
            {
                bool isValidProperty = false;
                if (!string.IsNullOrEmpty(this.APIOauthToken) && !string.IsNullOrEmpty(this.APIOauthTokenSecret) && !string.IsNullOrEmpty(this.APIOauthAccessKey) && !string.IsNullOrEmpty(this.APIOauthAccessToken) && !string.IsNullOrEmpty(this.UserID))
                {
                    isValidProperty = true;
                }
                return isValidProperty;
            }

            /// <summary>
            /// This method hits Twitter API and returns results/feeds in JSON format
            /// </summary>
            /// <returns></returns>
            private List<RootObject> GetTweets()
            {
                List<RootObject> objJson = null;
                // unique request details
                var oauth_nonce = Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
                var timeSpan = DateTime.UtcNow
                    - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
                var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();


                // create oauth signature
                var baseFormat = "oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                                "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&q={6}";
                var strResourceurl = "https://api.twitter.com/1.1/statuses/user_timeline.json";
                var baseString = string.Format(baseFormat,
                                        APIOauthAccessKey,
                                        oauth_nonce,
                                        OauthSignatureMethod,
                                        oauth_timestamp,
                                        APIOauthToken,
                                        OauthVersion,
                                        Uri.EscapeDataString(UserID)
                                            );

                baseString = string.Concat("GET&", Uri.EscapeDataString(strResourceurl), "&", Uri.EscapeDataString(baseString));

                var compositeKey = string.Concat(Uri.EscapeDataString(APIOauthAccessToken),
                                        "&", Uri.EscapeDataString(APIOauthTokenSecret));

                string oauth_signature;
                using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
                {
                    oauth_signature = Convert.ToBase64String(
                        hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
                }

                // create the request header
                var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
                                   "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
                                   "oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
                                   "oauth_version=\"{6}\"";


                var authHeader = string.Format(headerFormat,
                                        Uri.EscapeDataString(oauth_nonce),
                                        Uri.EscapeDataString(OauthSignatureMethod),
                                        Uri.EscapeDataString(oauth_timestamp),
                                        Uri.EscapeDataString(APIOauthAccessKey),
                                        Uri.EscapeDataString(APIOauthToken),
                                        Uri.EscapeDataString(oauth_signature),
                                        Uri.EscapeDataString(OauthVersion)
                                );
                ServicePointManager.Expect100Continue = false;
                // make the request
                var postBody = "q=" + Uri.EscapeDataString(UserID);//
                strResourceurl += "?" + postBody;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strResourceurl);
                request.Headers.Add("Authorization", authHeader);
                request.Method = "GET";
                request.ContentType = "application/x-www-form-urlencoded";
                var response = (HttpWebResponse)request.GetResponse();
                var reader = new StreamReader(response.GetResponseStream());
                var objText = reader.ReadToEnd();
                try
                {
                    objJson = JSONForTwitter.CreateFromString(objText);
                }
                catch (Exception ex)
                {
                    //Handle exception
                }
                return objJson;
            }
        }
    }
}
